home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / 001-025 / scopedisk1 / files / filereq.c next >
C/C++ Source or Header  |  1995-03-18  |  23KB  |  973 lines

  1.  
  2. /*
  3.  *  STDFILE -- Standard File Requestor. Version 2.0a 15 June 1987
  4.  *
  5.  *  AUTHOR -- Peter da Silva      US (713) 497-4372
  6.  *
  7.  *  Reorganized by Matthew Dillon for use with * and ?.  Added:
  8.  *    -device name in File string gadget transfered to directory
  9.  *     gadget without closing the window.
  10.  *    -bug when requesting volume ""... current directory lock would
  11.  *     get unlocked!
  12.  *    -additional intuitive features added
  13.  *    -coding reorganized
  14.  *
  15.  *    Copyright (c) 1987 Peter da Silva, all rights reserved.
  16.  *    Changes (c)Copyright 1987 Matthew Dillon, all rights reserved.
  17.  *
  18.  *    This module may be freely used in any product, commercial or
  19.  *    otherwise, provided credit is given for this module and
  20.  *    and provided this notice remains intact in the source. The
  21.  *    intent of this module is to provide a standard file requestor
  22.  *    such as is available on the Macintosh, in GEM on the IBM-PC
  23.  *    and Atari ST, and in the Microsoft Windows software on the
  24.  *    IBM-PC. The advantage this module has over other requestors
  25.  *    is that it minimises disk accesses: an important consideration
  26.  *    given the structure of AmigaDos directories. If you need to
  27.  *    modify it for your needs, by all means go ahead... but please
  28.  *    conform to the intent of this program as stated above. If you
  29.  *    have suggestions for improvements, by all means call me at
  30.  *    the number listed above.
  31.  *
  32.  * Enhancements in the current version:
  33.  *
  34.  *    Gadgets now boxed. Display generally cleaned up.
  35.  *
  36.  *    True "dictionary order" for searches.
  37.  *
  38.  *    Default pattern can now be specified. Default file name now
  39.  *    specified in a single argument.
  40.  *
  41.  *    Directories always match.
  42.  *
  43.  *    Null pattern converted to "#?" universal wildcard.
  44.  *
  45.  *    If you attempt to build a file name longer than 128 characters the
  46.  *    screen will flash and the operation will be aborted.
  47.  *
  48.  *    "Volumes" gadget, using the device list code in "mounted". This
  49.  *    gadget brings up a list of all currently mounted volumes for
  50.  *    selection. Volumes leaves the directory specification intact, so
  51.  *    you can quickly return to where you left off.
  52.  *
  53.  *    With these enhancements it is now possible to select any file on
  54.  *    any device without touching the keyboard. This is now release 2.0,
  55.  *    as it is significantly better than 1.0.
  56.  *
  57.  * Acknowledgements:
  58.  *
  59.  *    Thanks to Jeff Lydiatt for the pattern matching code in PatMatch.c
  60.  *    Thanks to Jay Miner, =RJ= and the whole Amiga team for the Amiga
  61.  *    itself.
  62.  *
  63.  * Environment:
  64.  *
  65.  *    IntuitionBase and GfxBase must be open. dos.library must be open
  66.  *    under the name "DosLibrary". Link with PatMatch.o and VolList.o.
  67.  *
  68.  * Usage:
  69.  *
  70.  *    #define MAXFILENAME 128
  71.  *
  72.  *    int stdfile(title, default_file, default_pat, name);
  73.  *    char *title;
  74.  *    char *default_file;
  75.  *    char *default_pattern;
  76.  *    char name[MAXFILENAME];
  77.  *
  78.  *    +-----------------------------------+
  79.  *    |o| Title ------------------- |  |  | title parameter, or "File Name"
  80.  *    |-----------------------------------|
  81.  *    | Directory: [              ] | Directory parameter, or current.
  82.  *    | File name: [              ] | Default parameter, or empty.
  83.  *    | Pattern:   [              ] | Initially empty, if the user
  84.  *    | +-------------------------------+ | enters anything here it will
  85.  *    | | [Filename]               |  | | be used to select files. The
  86.  *    | | [Filename]               |  | | file display will also be empty
  87.  *    | | [Filename]               |@@| | to start with to avoid excess
  88.  *    | | [Filename]               |@@| | disk I/O. If the user selects
  89.  *    | |                   |@@| | here the directory will be
  90.  *    | |                   |@@| | scanned looking for files
  91.  *    | |                   |  | | matching the specified pattern,
  92.  *    | |                   |  | | or "*" if no pattern is given.
  93.  *    | |                   |  | |
  94.  *    | +-------------------------------+ | ACCEPT returns 1. CANCEL
  95.  *    | [ACCEPT]    [VOLUMES]    [CANCEL] | or the close gadget return 0.
  96.  *    +-----------------------------------+ VOLUMES displays volume names.
  97.  *
  98.  *    The number of filenames displayed is specified at compile time in the
  99.  *    constant MAXFILES. The maximum size of a filename is specified in the
  100.  *    constant MAXNAME. The parameter "Default file" will be broken into
  101.  *    directory and file parts.
  102.  */
  103.  
  104. char *Copyright =
  105. "stdfile V2.0a. Copyright (c) 1987 Peter da Silva. All rights reserved.";
  106.  
  107. #include <intuition/intuitionbase.h>
  108. #include <intuition/intuition.h>
  109. #include <libraries/dos.h>
  110. #include <libraries/dosextens.h>
  111. #include <exec/memory.h>
  112.  
  113. typedef unsigned char  ubyte;
  114. typedef unsigned short uword;
  115. typedef unsigned long  ulong;
  116. typedef struct FileInfoBlock FIB;
  117. typedef struct DeviceList    DEVLIST;
  118. typedef struct DosLibrary    DOSLIB;
  119. typedef struct DosInfo         DOSINFO;
  120. typedef struct RootNode      ROOTNODE;
  121. typedef struct IntuiMessage  IMESS;
  122.  
  123. extern void CalcPropGadget();
  124. extern void ProcessFileName();
  125.  
  126. extern void *malloc();
  127. extern void *GetMsg();
  128. extern struct Window *OpenWindow();
  129.  
  130. #define MAXFILES 8
  131. #define MAXNAME 32
  132. #define MAXFULL (MAXNAME*4)
  133.  
  134. /* SIZING PARAMS */
  135.  
  136. #define Z        NULL
  137. #define INDENT        6
  138. #define LEFTMAR     (INDENT-1)
  139. #define BORDER        3
  140. #define CHSIZ        8
  141. #define HT        CHSIZ
  142. #define BASELINE    6
  143.  
  144. /* GADGET BORDERS */
  145.  
  146. #define IN1        LEFTMAR+10*CHSIZ
  147. #define IN3        LEFTMAR+3
  148. #define IN4        -(INDENT+6*CHSIZ+1)
  149. #define IN5        -(INDENT+CHSIZ*2)
  150. #define IN6        ((WINWD-WD6)/2)
  151. #define WD1        -(INDENT+IN1)
  152. #define WD3        (6*CHSIZ)
  153. #define WD4        (6*CHSIZ)
  154. #define WD5        (CHSIZ*2+2)
  155. #define WD6        (7*CHSIZ)
  156. #define TP1        (CHSIZ+BORDER)
  157. #define TP2        (TP1+HT+1)
  158. #define TP3        (TP2+HT+1)
  159. #define TP4        -(BORDER+HT4-1)
  160. #define TP5        (TP3+HT+BORDER)
  161. #define HT4        (HT+1)
  162. #define HT5        CHSIZ*MAXFILES+INDENT
  163.  
  164. #define WINHT        (TP5 + HT5 + (-TP4) + BORDER)
  165. #define WINWD        (INDENT*4 + (MAXNAME+2)*CHSIZ)
  166. #define WININ        (640-WINWD)/2
  167. #define WINTP        (200-WINHT)/2
  168.  
  169. #define HOMEX        (INDENT+LEFTMAR)
  170. #define HOMEY        (TP5+BORDER)
  171. #define LASTX        (HOMEX+MAXNAME*CHSIZ)
  172. #define LASTY        (HOMEY+MAXFILES*CHSIZ)
  173.  
  174. #define BTP        TP5
  175. #define BIN        LEFTMAR
  176. #define BWD        (WINWD-INDENT-BIN)
  177. #define BHT        (WINHT-BTP-(-TP4+BORDER+1))
  178.  
  179. #define SF        GADGHCOMP|GRELWIDTH
  180. #define SEL        SELECTED
  181. #define BF1        GADGHCOMP|GRELBOTTOM
  182. #define BF2        GADGHCOMP|GRELBOTTOM|GRELRIGHT
  183. #define PF        GRELRIGHT
  184.  
  185. #define SA        RELVERIFY
  186. #define CEN        STRINGCENTER
  187. #define BA        RELVERIFY
  188. #define PA        RELVERIFY
  189.  
  190. #define SI(n)      (APTR)&STD_String[n]
  191. #define G(n)       &STD_Gadget[n]
  192. #define IMAG       (APTR)&STD_Image
  193. #define PROP       (APTR)&STD_Prop
  194.  
  195. #define SG       STRGADGET
  196. #define BG       BOOLGADGET
  197. #define PG       PROPGADGET
  198.  
  199. #define FP       AUTOBACKPEN
  200. #define BP       AUTOFRONTPEN
  201.  
  202. #define OKTEXT       &STD_OK
  203. #define NOTEXT       &STD_CANCEL
  204. #define VLTEXT       &STD_VOLUME
  205.  
  206. static int DoneFlag;
  207.  
  208. #define DirName    SBuffer[0]
  209. #define FileName   SBuffer[1]
  210. #define PatName    SBuffer[2]
  211. #define STRINGS    3
  212.  
  213. static UBYTE SBuffer[STRINGS][MAXFULL];
  214. static UBYTE Undo[MAXFULL];
  215.  
  216. static struct StringInfo STD_String[STRINGS] = {
  217.     {SBuffer[0],Undo,0,MAXFULL,0},
  218.     {SBuffer[1],Undo,0,MAXFULL,0},
  219.     {SBuffer[2],Undo,0,MAXFULL,0}
  220. };
  221.  
  222. static struct PropInfo STD_Prop = { AUTOKNOB|FREEVERT, 0, 0, 0, 0 };
  223.  
  224. static struct IntuiText STD_OK =
  225.     { FP, BP, JAM2, 0, 1, Z, (UBYTE *)"ACCEPT", Z };
  226. static struct IntuiText STD_CANCEL =
  227.     { FP, BP, JAM2, 0, 1, Z, (UBYTE *)"CANCEL", Z };
  228. static struct IntuiText STD_VOLUME =
  229.     { FP, BP, JAM2, 0, 1, Z, (UBYTE *)"VOLUMES", Z };
  230.  
  231. #define BUTTONS 3
  232. #define BUTVEC 8
  233.  
  234. static SHORT butvecs[BUTTONS][BUTVEC*2] = {
  235.     { -2, HT4, -2, -1, WD3+1,-1, WD3+1,HT4, -3, HT4, -3,-1, WD3+2,-1, WD3+2, HT4 },
  236.     { -2, HT4, -2, -1, WD4+1,-1, WD4+1,HT4, -3, HT4, -3,-1, WD4+2,-1, WD4+2, HT4 },
  237.     { -2, HT4, -2, -1, WD6+1,-1, WD6+1,HT4, -3, HT4, -3,-1, WD6+2,-1, WD6+2, HT4 }
  238. };
  239.  
  240. static struct Border ButBorder[BUTTONS] = {
  241.     {0, 0, FP, BP, JAM1, BUTVEC, butvecs[0], NULL},
  242.     {0, 0, FP, BP, JAM1, BUTVEC, butvecs[1], NULL},
  243.     {0, 0, FP, BP, JAM1, BUTVEC, butvecs[2], NULL}
  244. };
  245.  
  246. #define BB(n) (APTR)&ButBorder[n]
  247.  
  248. static struct Image STD_Image;
  249.  
  250. #define DIRID 0
  251. #define FILID 1
  252. #define PATID 2
  253. #define YESID 3
  254. #define CANID 4
  255. #define VOLID 5
  256. #define BARID 6
  257. #define GADGETS 7
  258.  
  259. static struct Gadget STD_Gadget[GADGETS] = {
  260.     /*NEXT, LFT, TP,WDTH, H, FLAG,  ACT, TYP, REND, Z, TXT, Z, SPEC, ID, Z */
  261.     { G(1), IN1,TP1, WD1,HT, SF,     SA,  SG,    Z, Z,   Z, Z, SI(0), 0, 0 },
  262.     { G(2), IN1,TP2, WD1,HT, SF|SEL, SA,  SG,    Z, Z,   Z, Z, SI(1), 1, 0 },
  263.     { G(3), IN1,TP3, WD1,HT, SF,     SA,  SG,    Z, Z,   Z, Z, SI(2), 2, 0 },
  264.     { G(4), IN3,TP4, WD3,HT4,BF1,    BA,  BG,BB(0), Z, OKTEXT, Z,  Z, 3, 0 },
  265.     { G(5), IN4,TP4, WD4,HT4,BF2,    BA,  BG,BB(1), Z, NOTEXT, Z,  Z, 4, 0 },
  266.     { G(6), IN6,TP4, WD6,HT4,BF1,    BA,  BG,BB(2), Z, VLTEXT, Z,  Z, 5, 0 },
  267.     { NULL, IN5,TP5, WD5,HT5,PF,     PA,  PG, IMAG, Z,     Z, Z,    PROP, 6, 0 }
  268. };
  269.  
  270. static struct NewWindow STD_NewWindow = {
  271.     WININ, WINTP, WINWD, WINHT, -1, -1,
  272.     REFRESHWINDOW|MOUSEBUTTONS|GADGETUP|CLOSEWINDOW,
  273.     WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE|SIMPLE_REFRESH|ACTIVATE,
  274.     G(0), NULL, (ubyte *)"File Name Requestor",
  275.     NULL, NULL, 0, 0, 0, 0, WBENCHSCREEN
  276. };
  277.  
  278. static struct Window *STD_Window;
  279.  
  280. #define NVEC 6
  281.  
  282. static SHORT Vectors[NVEC*2] = {
  283.     BIN+1, BTP,
  284.     BIN+1, BTP+BHT,
  285.     BIN+BWD, BTP+BHT,
  286.     BIN+BWD, BTP,
  287.     BIN, BTP,
  288.     BIN, BTP+BHT
  289. };
  290.  
  291. static struct Border STD_FileBox = {
  292.     0, 0, FP, BP, JAM1, NVEC, Vectors, NULL
  293. };
  294.  
  295. static struct IntuiText STD_Text[3] = {
  296.     { FP, BP, JAM2, 0, 0, NULL, (UBYTE *)"Directory:", NULL },
  297.     { FP, BP, JAM2, 0, 0, NULL, (UBYTE *)"File Name:", NULL },
  298.     { FP, BP, JAM2, 0, 0, NULL, (UBYTE *)"Pattern:", NULL }
  299. };
  300.  
  301. static
  302. OpenFileWindow()
  303. {
  304.     extern struct IntuitionBase *IntuitionBase;
  305.     int i;
  306.  
  307.     /* Rebuild gadget list */
  308.  
  309.     STD_NewWindow.FirstGadget = &STD_Gadget[0];
  310.     for(i = 0; i < GADGETS; i++)
  311.     STD_Gadget[i].NextGadget = (i==GADGETS-1)?(0):(&STD_Gadget[i+1]);
  312.     for(i = 0; i < STRINGS; i++) {
  313.     STD_String[i].BufferPos = strlen(SBuffer[i]);
  314.     STD_String[i].DispPos = 0;
  315.     }
  316.     STD_Prop.VertBody = 0xFFFF;
  317.     STD_Prop.VertPot = 0;
  318.  
  319.     if (!(STD_Window = OpenWindow(&STD_NewWindow)))
  320.     return(0);
  321.  
  322.     /* This optional line will activate a string gadget     */
  323.     if (IntuitionBase->LibNode.lib_Version > 32)
  324.     ActivateGadget(G(1),STD_Window,0L);
  325.     CalcPropGadget();
  326.     PaintFileWindow();
  327.     return (1);
  328. }
  329.  
  330. static
  331. CloseFileWindow()
  332. {
  333.     STD_NewWindow.LeftEdge = STD_Window->LeftEdge;
  334.     STD_NewWindow.TopEdge = STD_Window->TopEdge;
  335.     if (STD_Window)
  336.     CloseWindow(STD_Window);
  337. }
  338.  
  339. static int State;
  340.  
  341. #define INITIAL 0
  342. #define DIRECTORY 1
  343.  
  344. static
  345. PaintFileWindow()
  346. {
  347.     DrawBorder(STD_Window->RPort, &STD_FileBox, 0, 0);
  348.     PrintIText(STD_Window->RPort, &STD_Text[0], LEFTMAR, TP1);
  349.     PrintIText(STD_Window->RPort, &STD_Text[1], LEFTMAR, TP2);
  350.     PrintIText(STD_Window->RPort, &STD_Text[2], LEFTMAR, TP3);
  351.     if (State == DIRECTORY)
  352.     PrintFileNames();
  353. }
  354.  
  355. static int FirstFile;
  356. static int Selected;
  357. static int NumFiles;
  358.  
  359. static struct dirent {
  360.     struct dirent *nextfile;
  361.     SHORT filetype;
  362.     char *filename;
  363. } *NameList, **NameTable;
  364.  
  365. #define FILETYPE 0
  366. #define DIRTYPE 1
  367. #define VOLTYPE 2
  368.  
  369. static
  370. PrintFileNames()
  371. {
  372.     int i;
  373.  
  374.     for (i = 0; i < MAXFILES; ++i) {
  375.     SetBPen(STD_Window->RPort, BP);
  376.     SetAPen(STD_Window->RPort, BP);
  377.     RectFill(STD_Window->RPort, HOMEX, HOMEY+i*CHSIZ, LASTX, HOMEY+(i+1)*CHSIZ);
  378.     if (i+FirstFile < NumFiles)
  379.         PrintName(i+FirstFile, i+FirstFile == Selected);
  380.     }
  381. }
  382.  
  383. static
  384. PrintName(file, hilite)
  385. int file;
  386. int hilite;
  387. {
  388.     int i;
  389.  
  390.     i = file - FirstFile;
  391.  
  392.     Move(STD_Window->RPort, HOMEX, HOMEY+i*CHSIZ+BASELINE);
  393.     if (hilite == 0) {
  394.     SetBPen(STD_Window->RPort, BP);
  395.     if(NameTable[file]->filetype == FILETYPE)
  396.         SetAPen(STD_Window->RPort, FP);
  397.     else
  398.         SetAPen(STD_Window->RPort, 3);
  399.     } else {
  400.     SetAPen(STD_Window->RPort, BP);
  401.     if(NameTable[file]->filetype == FILETYPE)
  402.         SetBPen(STD_Window->RPort, FP);
  403.     else
  404.         SetBPen(STD_Window->RPort, 3);
  405.     }
  406.     Text(STD_Window->RPort, NameTable[file]->filename, strlen(NameTable[file]->filename));
  407. }
  408.  
  409. static
  410. void
  411. CalcPropGadget()
  412. {
  413.     int VertPot, VertBody;
  414.  
  415.     if (State == INITIAL)
  416.     return;
  417.     if (NumFiles <= MAXFILES) {
  418.     VertBody = 0xFFFF;
  419.     VertPot = 0;
  420.     FirstFile = 0;
  421.     } else {
  422.     VertBody = ((MAXFILES<<16)-1) / NumFiles;
  423.     VertPot = 0;
  424.     FirstFile = 0;
  425.     }
  426.     ModifyProp(&STD_Gadget[BARID], STD_Window, NULL,
  427.     STD_Prop.Flags, 0, VertPot, 0, VertBody
  428.     );
  429. }
  430.  
  431. static
  432. void
  433. CalcFilePosition()
  434. {
  435.     short old_pos;
  436.  
  437.     if (State == INITIAL)
  438.      return;
  439.     old_pos = FirstFile;
  440.     if (NumFiles<=MAXFILES) {
  441.     FirstFile = 0;
  442.     } else {
  443.     int VertPot = STD_Prop.VertPot;
  444.     FirstFile = ((VertPot+1)*(NumFiles-MAXFILES))>>16;
  445.     }
  446.     if (old_pos != FirstFile)
  447.     PrintFileNames();
  448. }
  449.  
  450. FreeList(list)
  451. struct dirent *list;
  452. {
  453.     struct dirent *ptr;
  454.  
  455.     while(list) {
  456.     ptr = list->nextfile;
  457.     if (list->filename)
  458.         free(list->filename);
  459.     free(list);
  460.     list = ptr;
  461.     }
  462. }
  463.  
  464. static
  465. ReadNewDir()
  466. {
  467.     struct dirent *NewList, **NewTable, *ptr;
  468.     int NewCount;
  469.     FIB *fib;
  470.     BPTR dirlock;
  471.  
  472.     if (State != DIRECTORY) {
  473.     NameTable = 0;
  474.     NameList = 0;
  475.     }
  476.     if (DirName[0]) {
  477.         dirlock = Lock(DirName, ACCESS_READ);
  478.     } else {
  479.     BPTR ram;
  480.     if (ram = Lock("RAM:", ACCESS_READ)) {
  481.         dirlock = CurrentDir(ram);
  482.         CurrentDir(dirlock);
  483.         dirlock = DupLock(dirlock); /*  added */
  484.         UnLock(ram);
  485.     }
  486.     }
  487.     if (!dirlock)
  488.     return(0);
  489.     if ((fib = (FIB *)malloc(sizeof(FIB))) == NULL) {
  490.     UnLock(dirlock);
  491.     return 0;
  492.     }
  493.     if (!Examine(dirlock, fib)) {
  494.     UnLock(dirlock);
  495.     free(fib);
  496.     return 0;
  497.     }
  498.     if (fib->fib_DirEntryType < 0) {
  499.     UnLock(dirlock);
  500.     free(fib);
  501.     return 0;
  502.     }
  503.     NewList = 0;
  504.     NewCount = 0;
  505.     while(ExNext(dirlock, fib)) {
  506.     NewCount += 1;
  507.     ptr = (struct dirent *)malloc(sizeof(struct dirent));
  508.     if (ptr == 0) {
  509.         FreeList(NewList);
  510.         UnLock(dirlock);
  511.         free(fib);
  512.         return(0);
  513.     }
  514.     ptr->nextfile = NewList;
  515.     ptr->filetype = (fib->fib_DirEntryType<0)?FILETYPE:DIRTYPE;
  516.     ptr->filename = malloc(strlen(fib->fib_FileName)+1);
  517.     if (ptr->filename == 0) {
  518.         FreeList(ptr);
  519.         UnLock(dirlock);
  520.         free(fib);
  521.         return(0);
  522.     }
  523.     strcpy(ptr->filename, fib->fib_FileName);
  524.     NewList = ptr;
  525.     }
  526.     free(fib);
  527.     if (DirName[0])
  528.     UnLock(dirlock);
  529.     NewTable = malloc(sizeof(struct dirent *) * NewCount);
  530.     if (NewTable==0) {
  531.     FreeList(NewList);
  532.     return(0);
  533.     }
  534.     FreeList(NameList);
  535.     NameList = NewList;
  536.     if (NameTable)
  537.     free(NameTable);
  538.     NameTable = NewTable;
  539.     if (PatName[0]==0)
  540.     SetPatName("*");
  541.     State = DIRECTORY;
  542.     Selected = -1;
  543.     ReCalcPattern();
  544. }
  545.  
  546. static
  547. ReadVol()
  548. {
  549.     struct dirent *NewList, **NewTable, *ptr;
  550.     int NewCount;
  551.     char name[MAXNAME];
  552.  
  553.     if (State != DIRECTORY) {
  554.     NameTable = 0;
  555.     NameList = 0;
  556.     }
  557.     OpenVolList();
  558.     NewList = 0;
  559.     NewCount = 0;
  560.     while(ReadVolList(name)) {
  561.     NewCount += 1;
  562.     ptr = (struct dirent *)malloc(sizeof(struct dirent));
  563.     if (ptr==0) {
  564.         FreeList(NewList);
  565.         return(0);
  566.     }
  567.     ptr->nextfile = NewList;
  568.     ptr->filetype = VOLTYPE;
  569.     ptr->filename = malloc(strlen(name)+1);
  570.     if (ptr->filename == 0) {
  571.         FreeList(ptr);
  572.         return(0);
  573.     }
  574.     strcpy(ptr->filename, name);
  575.     NewList = ptr;
  576.     }
  577.     CloseVolList();
  578.     NewTable = malloc(sizeof(struct dirent *)*NewCount);
  579.     if (NewTable==0) {
  580.     FreeList(NewList);
  581.     return(0);
  582.     }
  583.     FreeList(NameList);
  584.     NameList = NewList;
  585.     if (NameTable)
  586.     free(NameTable);
  587.     NameTable = NewTable;
  588.  
  589.     if (PatName[0]==0)
  590.     SetPatName("*");
  591.  
  592.     State = DIRECTORY;
  593.     Selected = -1;
  594.  
  595.     ReCalcPattern();
  596. }
  597.  
  598. /* this routine does a true dictionary search:
  599.  *
  600.  *        Devs < devs but Devs > devices
  601.  */
  602.  
  603. static
  604. table_compare(p1, p2)
  605. struct dirent **p1, **p2;
  606. {
  607.     char *s1, *s2;
  608.     char c1, c2;
  609.     char firstdiff;
  610.  
  611.     s1 = (*p1)->filename;
  612.     s2 = (*p2)->filename;
  613.     firstdiff = 0;
  614.  
  615.     while(*s1 && *s2) {
  616.     c1 = *s1++;
  617.     c2 = *s2++;
  618.     if (firstdiff==0)
  619.         firstdiff = c1 - c2;
  620.     if (c1 >= 'A' && c1 <= 'Z') c1 = c1+'@';
  621.     if (c2 >= 'A' && c2 <= 'Z') c2 = c2+'@';
  622.     if (c1 != c2)
  623.         return c1 - c2;
  624.     }
  625.     return firstdiff;
  626. }
  627.  
  628. static
  629. sort_table()
  630. {
  631.     qsort(NameTable, NumFiles, sizeof(struct dirent *), table_compare);
  632.     return 1;
  633. }
  634.  
  635. static
  636. ReCalcPattern()
  637. {
  638.     if (State != DIRECTORY) {
  639.     ReadNewDir();
  640.     } else {
  641.     struct dirent *ptr;
  642.  
  643.     if (!PatName[0])
  644.         SetPatName("*");
  645.     NumFiles = 0;
  646.     for (ptr = NameList; ptr; ptr=ptr->nextfile) {
  647.         /* Directories always match. Is this good? */
  648.         if (ptr->filetype == DIRTYPE || ptr->filetype == VOLTYPE || newwildcmp(PatName, ptr->filename)) {
  649.         NameTable[NumFiles] = ptr;
  650.         NumFiles++;
  651.         }
  652.     }
  653.     sort_table();
  654.     CalcPropGadget();
  655.     Selected = -1;
  656.     PrintFileNames();
  657.     }
  658. }
  659.  
  660. static
  661. SetGadgetText(id, text)
  662. int id;
  663. char *text;
  664. {
  665.     int position;
  666.  
  667.     position = RemoveGadget(STD_Window, G(id));
  668.     if (position != -1) {
  669.     strcpy(SBuffer[id], text);
  670.     STD_String[id].BufferPos = strlen(text);
  671.     position = AddGadget(STD_Window, G(id), -1);
  672.     if (position != -1)
  673.         RefreshGadgets(G(id), STD_Window, NULL);
  674.     }
  675. }
  676.  
  677. static
  678. SetDirName(name)
  679. char *name;
  680. {
  681.     char buffer[MAXFULL+1], *ptr;
  682.     int  index;
  683.     char lastchar;
  684.  
  685.     /* Can't enter a file name too long. */
  686.  
  687.     if (strlen(DirName) + strlen(name) + 1 > MAXFULL) {
  688.     DisplayBeep();
  689.     return(0);
  690.     }
  691.     index = 0;
  692.     lastchar = 0;
  693.     for (ptr = (char *)DirName; *ptr; ptr++)
  694.     buffer[index++] = lastchar = *ptr;
  695.     if (lastchar != ':' && lastchar != 0)
  696.     buffer[index++] = '/';
  697.     strcpy(&buffer[index], name);
  698.     SetGadgetText(DIRID, buffer);
  699.     SetGadgetText(FILID, "");
  700.     return(1);
  701. }
  702.  
  703. static
  704. SetFileName(name)
  705. char *name;
  706. {
  707.     /* Can't enter a file name too long. */
  708.     if (strlen(DirName) + strlen(name) + 1 > MAXFULL) {
  709.     DisplayBeep();
  710.     return(0);
  711.     }
  712.     SetGadgetText(FILID, name);
  713.     return(1);
  714. }
  715.  
  716. static
  717. SetPatName(name)
  718. char *name;
  719. {
  720.     SetGadgetText(PATID, name);
  721. }
  722.  
  723. static
  724. ProcessGadget(id)
  725. int id;
  726. {
  727.     switch(id) {
  728.     case DIRID: ReadNewDir();       break;
  729.     case FILID: ProcessFileName();  break;
  730.     case PATID: ReCalcPattern();    break;
  731.     case BARID: CalcFilePosition(); break;
  732.     case YESID: DoneFlag = 1;        break;
  733.     case CANID: DoneFlag = -1;        break;
  734.     case VOLID: ReadVol();          break;
  735.     }
  736. }
  737.  
  738. /*
  739.  *  ProcessFileName() added by Matthew Dillon.  If the requested file is
  740.  *  actually a directory, do a ReadNewDir() instead of quiting.
  741.  */
  742.  
  743. void
  744. ProcessFileName()
  745. {
  746.     register char *ptr;
  747.     register short len;
  748.     BPTR fillock;
  749.     char buf[128];
  750.     FIB *fib = (FIB *)malloc(sizeof(FIB));
  751.  
  752.     if (fib == NULL) {
  753.     DoneFlag = 1;
  754.     return;
  755.     }
  756.     for (ptr = (char *)FileName; *ptr; ++ptr) {
  757.     if (*ptr == ':') {
  758.         DirName[0] = '\0';
  759.         break;
  760.     }
  761.     }
  762.     strcpy(buf, DirName);
  763.     if (FileName[0]) {
  764.     if (len = strlen(buf)) {
  765.         if (buf[len-1]!=':')
  766.         strcat(buf, "/");
  767.     }
  768.     strcat(buf, FileName);
  769.     if (fillock = Lock(buf, ACCESS_READ)) {
  770.         if (Examine(fillock, fib)) {
  771.         if (fib->fib_DirEntryType > 0) {
  772.             SetGadgetText(DIRID, buf);
  773.             SetGadgetText(FILID, "");
  774.             ReadNewDir();
  775.             free(fib);
  776.             UnLock(fillock);
  777.             return;
  778.         }
  779.         }
  780.         UnLock(fillock);
  781.     }
  782.     }
  783.     free(fib);
  784.     DoneFlag = 1;
  785. }
  786.  
  787. static
  788. ProcessMouse(x, y, code, seconds, micros)
  789. {
  790.     int NewSelected;
  791.     static int oseconds = 0, omicros = 0;
  792.  
  793.     if (x < HOMEX || y < HOMEY || x >= LASTX || y >= LASTY)
  794.     return;
  795.     if ((code & SELECTUP) == SELECTUP)
  796.     return;
  797.     if (State != DIRECTORY) {
  798.     ReadNewDir();
  799.     return;
  800.     }
  801.     NewSelected = (y-HOMEY)/CHSIZ + FirstFile;
  802.     if (NewSelected == Selected) {
  803.     if (Selected != -1) {
  804.         if (DoubleClick(oseconds, omicros, seconds, micros)) {
  805.         if (NameTable[Selected]->filetype == DIRTYPE) {
  806.             if (SetDirName(NameTable[Selected]->filename))
  807.             ReadNewDir();
  808.         } else if (NameTable[Selected]->filetype == VOLTYPE) {
  809.             SetGadgetText(DIRID, NameTable[Selected]->filename);
  810.             SetGadgetText(FILID, "");
  811.             ReadNewDir();
  812.         } else if (!SetFileName(NameTable[Selected]->filename)) {
  813.             Selected = -1;
  814.             DoneFlag = 1;
  815.         }
  816.         }
  817.     }
  818.     } else {
  819.     if (Selected != -1 && Selected >= FirstFile && Selected < FirstFile+MAXFILES)
  820.         PrintName(Selected, 0);
  821.     Selected = NewSelected;
  822.     if (Selected >= NumFiles) {
  823.         Selected = -1;
  824.     } else {
  825.         if (SetFileName(NameTable[Selected]->filename))
  826.         PrintName(Selected, 1);
  827.         else
  828.         Selected = -1;
  829.         if (IntuitionBase->LibNode.lib_Version > 32)
  830.         ActivateGadget(G(1),STD_Window,0L);
  831.     }
  832.     }
  833.     oseconds = seconds;
  834.     omicros = micros;
  835. }
  836.  
  837. stdfile(title, deffile, defpat, name)
  838. char *title, *deffile, *defpat, *name;
  839. {
  840.     IMESS *im;
  841.  
  842.     if(title)
  843.     STD_NewWindow.Title = (UBYTE *)title;
  844.     else
  845.     STD_NewWindow.Title = (UBYTE *)"Enter File Name";
  846.     if (deffile) {
  847.     int i;
  848.     for (i = strlen(deffile)-1; i >= 0; --i) {
  849.         if (deffile[i]==':' || deffile[i]=='/') {
  850.         int hold;
  851.         strcpy(FileName, &deffile[i+1]);
  852.         if (deffile[i]==':')
  853.             i++;
  854.         hold = deffile[i];
  855.         deffile[i] = 0;
  856.         strcpy(DirName, deffile);
  857.         deffile[i] = hold;
  858.         break;
  859.         }
  860.     }
  861.     if (i < 0) {
  862.         strcpy(FileName, deffile);
  863.         DirName[0] = 0;
  864.     }
  865.     } else {
  866.     DirName[0] = 0;
  867.     FileName[0] = 0;
  868.     }
  869.     if (defpat)
  870.     strcpy(PatName, defpat);
  871.     else
  872.     PatName[0] = 0;
  873.  
  874.     State = INITIAL;
  875.     NameTable = 0;
  876.     NameList = 0;
  877.  
  878.     if(!OpenFileWindow())
  879.     return(0);
  880.     DoneFlag = 0;
  881.     while (!DoneFlag) {
  882.     Wait(1<<STD_Window->UserPort->mp_SigBit);
  883.     while(im = GetMsg(STD_Window->UserPort)) {
  884.         switch(im->Class) {
  885.         case CLOSEWINDOW:
  886.         DoneFlag = -1;
  887.         break;
  888.         case MOUSEBUTTONS:
  889.         ProcessMouse(im->MouseX, im->MouseY, im->Code, im->Seconds, im->Micros);
  890.         break;
  891.         case GADGETUP:
  892.         ProcessGadget(((struct Gadget *)im->IAddress)->GadgetID);
  893.         break;
  894.         case REFRESHWINDOW:
  895.         BeginRefresh(STD_Window);
  896.         PaintFileWindow();
  897.         EndRefresh(STD_Window, 1);
  898.         break;
  899.         }
  900.         ReplyMsg(im);
  901.     }
  902.     }
  903.     CloseFileWindow();
  904.     FreeList(NameList);
  905.  
  906.     if (NameTable)
  907.     free(NameTable);
  908.     if (DoneFlag == 1) {
  909.     int len;
  910.  
  911.     strcpy(name, DirName);
  912.     if (FileName[0]) {
  913.         if (len = strlen(name)) {
  914.         if (name[len-1]!=':')
  915.             strcat(name, "/");
  916.         }
  917.         strcat(name, FileName);
  918.         return(1);
  919.     }
  920.     }
  921.     return(0);
  922. }
  923.  
  924. /*
  925.  *  VOLLIST.C
  926.  */
  927.  
  928. #define toAPTR(b) ((b)<<2)
  929. #define toBPTR(a) ((a)>>2)
  930.  
  931. struct DeviceList *list;
  932.  
  933. OpenVolList()
  934. {
  935.     extern DOSLIB *DOSBase;
  936.     ROOTNODE *root;
  937.     DOSINFO  *info;
  938.  
  939.     root =   (ROOTNODE *)DOSBase->dl_Root;
  940.     info =   (DOSINFO  *)toAPTR(root->rn_Info);
  941.     list = (DEVLIST *)toAPTR(info->di_DevInfo);
  942. }
  943.  
  944. ReadVolList(name)
  945. char *name;
  946. {
  947.     register DEVLIST *next;
  948.  
  949.     while(list) {
  950.     next = (DEVLIST *)toAPTR(list->dl_Next);
  951.     if (list->dl_Type == DLT_VOLUME) {
  952.         char *ptr;
  953.         int count;
  954.         ptr = (char *)toAPTR((BPTR)list->dl_Name);
  955.         count = *ptr++;
  956.         if (count > 30)
  957.         count = 30;
  958.         strncpy(name, ptr, count);
  959.         name[count++] = ':';
  960.         name[count] = 0;
  961.         list = next;
  962.         return(1);
  963.     }
  964.     list = next;
  965.     }
  966.     return(0);
  967. }
  968.  
  969. CloseVolList()
  970. {
  971. }
  972.  
  973.